package http

import (
	"context"
	"fmt"
	"github.com/gin-gonic/gin"
	"go.uber.org/zap"
	"net"
	"net/http"
	"wzgames/pkg/logger"
)

// gin server

type HttpS struct {
	router   *gin.Engine
	httpServ *http.Server
	listener net.Listener

	conf *HttpConfig
}

type HttpConfig struct {
	ServID int64  `yaml:"serv_id"` // admin.sql#sys_servs
	Ip     string `yaml:"ip"`
	Port   string `yaml:"port"`
	Mod    string `yaml:"mod"` // gin mode
}

func NewHttpServer(conf *HttpConfig, opts ...HttpOption) *HttpS {
	s := &HttpS{
		conf: conf,
	}

	gin.SetMode(conf.Mod)
	s.router = gin.New()

	// init routes
	for _, o := range opts {
		o(s.router)
	}

	return s
}

func (h *HttpS) Start(ctx context.Context) error {
	if err := h.serve(false); err != nil {
		logger.Error("[HttpS] server start fail", zap.Error(err))
		return err
	}

	logger.Info("[HttpS] server started", zap.String("Address", fmt.Sprintf("%s:%s", h.conf.Ip, h.conf.Port)))

	return nil
}

func (h *HttpS) Stop(ctx context.Context) error {
	err := h.httpServ.Shutdown(ctx)
	if err != nil {
		logger.Error("[HttpS] server shutdown error", zap.Error(err))
		return err
	}

	logger.Error("[HttpS] server shutdown")
	return nil
}

func (h *HttpS) serve(graceful bool) (err error) {
	addr := fmt.Sprintf("%s:%s", h.conf.Ip, h.conf.Port)
	httpServer := &http.Server{
		Addr:    addr,
		Handler: h.router,
	}
	if graceful { // TODO

	} else {
		h.listener, err = net.Listen("tcp", addr)
	}
	if err != nil {
		logger.Error("[HttpS] server listener fail", zap.Error(err))
		return
	}

	h.httpServ = httpServer

	go func() {
		if e := httpServer.Serve(h.listener); e != nil && e != http.ErrServerClosed {
			logger.Fatal("[HttpS] server serve fatal", zap.Error(e))
		}
	}()

	return
}
